package com.liam.es.util.similarity;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * 两个集合A和B交集元素的个数在A、B并集中所占的比例，称为这两个集合的杰卡德系数
 * |A 交集 B| / |A 并集 B |
 * */

@Slf4j
public class JaccardSimilarity {

    /**
     * 1、计算两个字符串的相似度
     */
    public static double getSimilarity(String text1, String text2) {

        //如果空，或者字符长度为0，则代表完全相同
        if (StringUtils.isBlank(text1) && StringUtils.isBlank(text2)) {
            return 1.0;
        }
        //如果一个为0或者空，一个不为，那说明完全不相似
        if (StringUtils.isBlank(text1) || StringUtils.isBlank(text2)) {
            return 0.0;
        }
        if (text1.equalsIgnoreCase(text2)) {
            return 1.0;
        }
        //第一步：进行分词
        List<String> words1 = Tokenizer.segmentStr(text1);
        List<String> words2 = Tokenizer.segmentStr(text2);

        return getSimilarity(words1, words2);
    }

    /**
     * 2、对于计算出的相似度保留小数点后六位
     */
    public static double getSimilarity(List<String> words1, List<String> words2) {

        Set<String> words2Set = new HashSet<>();
        words2Set.addAll(words2);

        //求交集
        Set<String> intersectionSet = new ConcurrentSkipListSet<>();
        words1.parallelStream().forEach(word -> {
            if (words2Set.contains(word)) {
                intersectionSet.add(word);
            }
        });
        //求并集
        Set<String> unionSet = new HashSet<>();
        words1.forEach(word -> unionSet.add(word));
        words2.forEach(word -> unionSet.add(word));

        //相似度分值
        double score = intersectionSet.size() / (double) unionSet.size();

        return score;
    }


    public static void main(String[] args) {
        String content1 = "今天天气真好";
        String content2 = "今天天气不错";

        content1 = "今天小小和爸爸一起去摘草莓，小小说今天的草莓特别的酸，而且特别的小，关键价格还贵";
        content2 = "今天小小和妈妈一起去草原里采草莓，今天的草莓味道特别好，而且价格还挺实惠的";

        content1 = "电视剧《赘婿》中宁毅的真实身份叫什么？";
        content2 = "电视剧《赘婿》中宁毅最先教了谁腌制皮蛋？";
        JaccardSimilarity.getSimilarity(content1,content2);
    }

}
